﻿using Entity;
using Global;
using Global.ExtensionMethods;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using System.Data;
using System.Windows.Markup;
using ViewModels.Components;
using ViewModels.LogOn;
using ViewModels.Pwd;
using ViewModels.User;
using static Global.Const;

namespace ProdService
{
    public class UserService : BaseService
    {
        private readonly PhoneService _phoneService;

        public UserService(DbContext dbContext, IHttpContextAccessor accessor, PhoneService phoneService) :
            base(dbContext, accessor)
        {
            _phoneService = phoneService;
        }

        public INameModel GetNames(int id)
        {
            User user = dbContext.Set<User>().Find(id);
            return mapper.Map<NameModel>(user);
        }

        public int Register(RegisterModel model)
        {
            model.Password = model.Password?.Md5Encypt();
            User user = mapper.Map<User>(model);
            if (!string.IsNullOrEmpty(model.InviteCode))
            {
                user.InvitedBy = dbContext.Set<User>()
                    .Find(Convert.ToInt32(getUserIdBy(model.InviteCode)));
            }
            user.Register();
            Phone phone = _phoneService.GetBy(model.Number);
            phone.User = user;
            dbContext.Add<User>(user);
            dbContext.SaveChanges();
            return user.Id;
        }

        /// <summary>
        /// 除本人以外，有无其他人使用该用户名
        /// </summary>
        /// <param name="logonName"></param>
        /// <returns></returns>
        public bool NameHasUsed(string logonName)
        {
            User user = GetByName(logonName);
            if (user == null)
            {
                return false;
            }//else查到了一个用户，继续……

            User current = GetCurrentUser();
            //1、但是当前用户未登录，或者当前用户就是查到的这个用户
            if (current == null ||
                current.Id == user.Id)
            {
                return false;
            }

            return true;
        }

        public NavigatorModel GetNav()
        {
            NavigatorModel model = null;
            User user = GetCurrentUser();
            if (user != null)
            {
                model = mapper.Map<NavigatorModel>(user);
            }//else nothing
            return model;
        }

        public User GetByName(string userName)
        {
            return dbContext.Set<User>()
                .Where(u => u.LogonName == userName).SingleOrDefault();
        }

        public _InviteCodeModel GetInviteCode()
        {
            User user = GetCurrentUser();

            _InviteCodeModel model = mapper.Map<_InviteCodeModel>(user);
            model.Invitees = mapper.Map<IList<NavigatorModel>>(
                dbContext.Set<User>().Where(u => u.InvitedById == user.Id).ToList()
                );
            return model;
        }

        public bool CheckInvited(string inviteCode)
        {
            bool canParse = int.TryParse(getUserIdBy(inviteCode), out int userId);
            if (!canParse)
            {
                return false;
            }
            User user = dbContext.Set<User>().Find(userId);
            if (user == null)
            {
                return false;
            }
            return user.InviteCode == getCodeBy(inviteCode);
        }

        public bool IsPasswordCorrect(string password)
        {
            return IsPasswordCorrect(GetCurrentUser(), password);
        }
        public bool IsPasswordCorrect(User user, string password)
        {
            return password.Md5Encypt() == user.Password;
        }

        public void On(int userId, bool remember)
        {
            User user = dbContext.Set<User>().Find(userId);
            logOn(user, remember);
        }

        public void SetPwd(string password)
        {
            GetCurrentUser().Password = password.Md5Encypt();
        }

        public int ResetPwd(ResetModel model)
        {
            Phone phone = _phoneService.GetBy(model.Number);
            User user = phone.User;
            user.Password = model.Password.Md5Encypt();
            return user.Id;
        }

        public void ChangeNames(NameModel model)
        {
            mapper.Map(model, GetCurrentUser());
        }

        #region Private Methods

        private string getUserIdBy(string inviteCode)
        {
            return inviteCode.Substring(0, inviteCode.IndexOf('-'));
        }

        private string getCodeBy(string inviteCode)
        {
            return inviteCode.Substring(inviteCode.IndexOf('-') + 1);
        }

        private void logOn(User user, bool remember)
        {
            int? days = remember ? Config.Template.RememberDays : (int?)null;
            setUserCookie(user, days);

        }

        private void setUserCookie(User user, int? days = null)
        {
            CookieOptions options = new();
            if (days != null)
            {
                options.Expires = new DateTimeOffset(DateTime.Now, TimeSpan.FromDays(days.Value));
            }
            httpContext.Response.Cookies.Append(CookieName.UserId, user.Id.ToString(), options);
            httpContext.Response.Cookies.Append(CookieName.Password, user.Password.Md5Encypt(), options);
        }



        #endregion

    }
}